import * as ImgCompressor from 'img-compressor';
import store from "@/store";
import {ElMessage} from "element-plus";
import router from "@/router";
import websocket from "@/utils/websocket";

/**
 * 重新登录.
 */
export const resetLogin = function (tip = '请重新登录') {
    if (store.state.isShowMsg) {
        return;
    }
    store.commit('setIsShowMsg', true);
    ElMessage.error({
        message: tip,
        duration: 1000,
        onClose: () => {
            logoutClear();
        }
    });
}

/**
 * 退出清理
 */
export const logoutClear = function () {
    try {
        store.commit('clearUserToken');
        store.commit('clearUserInfo');
        if (websocket?.isConnected) {
            websocket.closeSocket();
        }
    } finally {
        router.push('/login');
    }
};

/**
 * 消息弹框
 * @param message
 */
export const showMessage = function (message) {
    if (store.state.isShowMsg) {
        return Promise.reject(message)
    }
    store.commit('setIsShowMsg', true);
    ElMessage.error({
        message: message || '操作失败',
        onClose: () => store.commit('setIsShowMsg', false)
    });
    return Promise.reject(message || '操作失败');
}

/**
 * 深度复制
 * @param obj
 * @returns {any}
 */
export const deepCopy = (obj) => {
    return JSON.parse(JSON.stringify(obj))
}

/**
 * 获取文件base64
 * @param {*} file
 * @returns
 */
export const getBase64 = (file) => {
    return new Promise(function (resolve, reject) {
        let reader = new FileReader();
        let imgResult = "";
        reader.readAsDataURL(file);
        reader.onload = function () {
            imgResult = reader.result;
        };
        reader.onerror = function (error) {
            reject(error);
        };
        reader.onloadend = function () {
            resolve(imgResult);
        };
    });
};

/**
 * blob转file文件
 * @param {*} blob
 * @param {*} name
 * @param {*} type
 * @returns
 */
export const blobToFile = function (blob, name, type) {
    return new File([blob], name, {type: type});
}

/**
 * 图片压缩方法
 * @param {
 *  file： 需要压缩的图片
 *  width: 图片宽度
 *  height： 图片高度
 *  size： 压缩结果不能大于多少 单位m
 *  name: 文件名称
 *  type： 文件类型
 * }
 * @returns 返回promise对象 参数压缩后的图片
 */
export const imgCompressor = ({blob, width, height, size = 1, name, type}) => {
    const imgCompressor = new ImgCompressor.Create({
        width, height
    });
    return new Promise((resolve, reject) => {
        function compress(blob) {
            imgCompressor.compress(blob, {
                success: function (result) {
                    if (result.size / 1024 / 1024 > size) {
                        compress(result)
                    } else {
                        resolve(blobToFile(result, name, type));
                    }
                }, err: function () {
                    reject('图片压缩失败');
                }
            })
        }

        compress(blob)
    })
}

/**
 * 创建对象副本，根据对象 以及字段生成新的对象
 * @param {*} obj
 * @param {*} arr 需要保留的字段数组
 */
export const createObjectBase = (obj, arr) => {
    const item = deepCopy(obj);
    const base = {};
    arr.forEach(key => {
        base[key] = item[key]
    })
    return base
}

/**
 * 下载二进制文件
 * @param data 二进制数据
 * @param fileName 文件名
 */
export const downloadFileByByte = (data, fileName) => {
    const raw = atob(data);
    const rawLength = raw.length;
    const uInt8Array = new Uint8Array(rawLength);
    for (let i = 0; i < rawLength; ++i) {
        uInt8Array[i] = raw.charCodeAt(i);
    }
    downloadFileByBlob(uInt8Array, fileName);
}

/**
 * 下载文件
 * @param data 数据
 * @param fileName 文件名
 */
export const downloadFileByBlob = (data, fileName) => {
    const blob = new Blob([data]);
    if (navigator.msSaveOrOpenBlob) {
        // 兼容ie
        navigator.msSaveBlob(blob, fileName);
    } else {
        const downloadLink = document.createElement('a');
        downloadLink.style.display = 'none';
        downloadLink.href = URL.createObjectURL(blob);
        downloadLink.download = fileName;
        document.body.appendChild(downloadLink);
        downloadLink.click();
        document.body.removeChild(downloadLink);
        URL.revokeObjectURL(downloadLink.href);
    }
}

/**
 * 下载文件
 * @param contentDisposition
 * @param data
 */
export const downloadFileByResponse = (contentDisposition, data) => {
    if (!contentDisposition) {
        return;
    }
    // const filenameFromCD = contentDisposition?.split('filename=')[1]?.replace(/"/g, '');
    let pattern = new RegExp('filename=([^;]+\\.[^\\.;]+);*');
    let result = pattern.exec(contentDisposition);
    // 使用decodeURI对名字进行解码
    let fileName = decodeURI(result[1]);
    if (!fileName) {
        return;
    }

    downloadFileByBlob(data, fileName);
}

/**
 * 获取树形结构选中的节点
 * @param arr
 * @returns {*[]}
 */
export const getTreeByCheck = (arr) => {
    const resultList = [];
    arr.forEach((item) => {
        if (item.children && item.children.length) {
            resultList.push(...getTreeByCheck(item.children));
        } else {
            if (item.checked) {
                resultList.push(item);
            }
        }
        if (item.checked && item.parentId) {
            resultList.push(item);
        }
    });
    let data = [...new Set(resultList)];
    return data;
}

/**
 * 获取树形结构选中的节点id
 * @param tree
 * @returns {*[]}
 */
export const getSelectIds = (tree) => {
    return tree ? [...tree.getHalfCheckedKeys(), ...tree.getCheckedKeys()] : [];
}

/**
 * 生成指定长度的随机字符串
 * @param {number} length - 字符串长度，默认12
 * @returns {string}
 */
export const generateRandomString = (length = 12) => {
    const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    let result = '';
    for (let i = 0; i < length; i++) {
        result += chars.charAt(Math.floor(Math.random() * chars.length));
    }
    return result;
};

/**
 * 把嵌套对象/数组扁平化为 Map
 * @param {Object|Array} data 原始数据
 * @param {String} prefix 父级 key（内部递归用）
 * @returns {Object} 扁平结果
 */
export const flattenData = (data, prefix = '') => {
    const result = {};

    const temp = (val, pre) => {
        // 去掉 null、undefined、空字符串
        if (val == undefined || val == null || val === '') return;

        if (val && typeof val === 'object' && !Array.isArray(val)) {
            Object.keys(val).forEach(k => temp(val[k], pre ? `${pre}.${k}` : k));
        } else if (Array.isArray(val)) {
            val.forEach((item, idx) => temp(item, `${pre}[${idx}]`));
        } else {
            result[pre] = val;
        }
    };

    temp(data, prefix);
    return result;
}

/**
 * 生成签名字符串（排序 + 拼接）
 */
export const toFlattenDataSign = (obj) => {
    const flatMap = flattenData(obj);
    return Object.keys(flatMap)
        .sort()
        .map(k => `${k}=${flatMap[k]}`)
        .join('&');
};

